#include "vt100.h"
#include "my_console.h"

#include "utf8.h"
#include "char.h"

#include <stdio.h>
#include <wchar.h>
#include <string.h>
#include <cstdlib>
#include <conio.h>   // 包含 kbhit() 和 getch() 函数的头文件
#include <windows.h> // 包含 Sleep() 函数的头文件

// 01111110
// 0111 1110
static uint8_t NUM1_0[] = {
    0x00, 0x44, 0x7E, 0x40, // "1"
    0x44, 0x62, 0x52, 0x4c, // "2"
    0x20, 0x4a, 0x4a, 0x34, // "3"
    0x30, 0x24, 0x7e, 0x20, // "4"
    0x24, 0x4a, 0x4a, 0x3a, // "5"
    0x7e, 0x4a, 0x4a, 0x7a, // "6"
    0x04, 0x02, 0x7a, 0x06, // "7"
    0x7e, 0x4a, 0x4a, 0x3e, // "8"
    0x6e, 0x4a, 0x4a, 0x3e, // "9"
    0x7c, 0x42, 0x42, 0x3c, // "0"
};

static uint8_t MA[] = {
    0x00,
    0x00,
    0x80,
    0x07,
    0x60,
    0x0E,
    0x40,
    0x06,
    0x40,
    0x06,
    0x40,
    0x06,
    0x40,
    0x02,
    0xE0,
    0x7F,
    0x00,
    0x60,
    0x80,
    0x23,
    0xFC,
    0x20,
    0x00,
    0x30,
    0x00,
    0x1E,
    0x00,
    0x08,
    0x00,
    0x00,
    0x00,
    0x00,
};

typedef struct
{
    uint32_t x;
    uint32_t y;
} STPoint;

typedef struct
{
    STPoint p;
    uint32_t width;
    uint32_t height;
} STRect;

// 在指定区域绘制文本，小于宽度，居中； 换行/不绘制

void DrawNum()
{
    static uint8_t num = 0;

    int x = (80 - 16) / 2, y = 2;

    SetBgColor(VT_B_BLUE);
    FillBox(x, y, 16, 8);

    SetBgColor(VT_B_CYAN);

    for (int i = 0; i < 4; i++)
    {
        uint8_t numData = NUM1_0[4 * num + i];
        for (int j = 0; j < 8; j++)
        {
            if (numData & (0x01 << j))
            {
                FillBox(x + 2 * i, y + j, 2, 1);
            }
        }
    }
    num++;
    num %= 10;
}

void DrawZh()
{
    SetBgColor(VT_B_BLUE);
    FillBox(1, 1, 1 + 16 * 2, 1 + 16);

    SetBgColor(VT_B_CYAN);

    int x = 2, y = 1;

    static int num = 0;

    int tmp = num % 16;

    for (int i = 0; i < 16; i++)
    {
        tmp++;
        if (tmp >= 16)
            tmp = 0;
        for (int k = 0; k < 2; k++)
        {
            uint8_t zhData = MA[2 * tmp + k];
            for (int j = 0; j < 8; j++)
            {
                if (zhData & (0x01 << j))
                {
                    FillBox(x + 2 * j + 2 * k * 8, y + i, 2, 1);
                }
            }
        }
    }

    num++;
}
size_t calculateActualWidth(const wchar_t *wcStr);

int my_wctomb(char *mbstr, wchar_t wc)
{
    // 如果输入是一个无效的宽字符，返回 -1
    if (wc < 0 || wc > 0x10FFFF)
    {
        return -1;
    }

    // 判断字符的编码范围，并按 UTF-8 编码规则处理
    if (wc <= 0x7F)
    {
        // 1字节字符 (0x00 - 0x7F)
        mbstr[0] = (char)wc;
        mbstr[1] = '\0';
        return 1;
    }
    else if (wc <= 0x7FF)
    {
        // 2字节字符 (0x80 - 0x7FF)
        mbstr[0] = (char)((wc >> 6) | 0xC0);   // 110xxxxx
        mbstr[1] = (char)((wc & 0x3F) | 0x80); // 10xxxxxx
        mbstr[2] = '\0';
        return 2;
    }
    else if (wc <= 0xFFFF)
    {
        // 3字节字符 (0x800 - 0xFFFF)
        mbstr[0] = (char)((wc >> 12) | 0xE0);         // 1110xxxx
        mbstr[1] = (char)(((wc >> 6) & 0x3F) | 0x80); // 10xxxxxx
        mbstr[2] = (char)((wc & 0x3F) | 0x80);        // 10xxxxxx
        mbstr[3] = '\0';

        return 3;
    }
    else if (wc <= 0x10FFFF)
    {
        // 4字节字符 (0x10000 - 0x10FFFF)
        mbstr[0] = (char)((wc >> 18) | 0xF0);          // 11110xxx
        mbstr[1] = (char)(((wc >> 12) & 0x3F) | 0x80); // 10xxxxxx
        mbstr[2] = (char)(((wc >> 6) & 0x3F) | 0x80);  // 10xxxxxx
        mbstr[3] = (char)((wc & 0x3F) | 0x80);         // 10xxxxxx
        mbstr[4] = '\0';
        return 4;
    }

    return -1; // 如果字符超出有效范围，返回 -1
}

// 将 wchar_t 字符转换为 UTF-8 字符串
void wcharToUtf8(wchar_t wc, char *utf8_str)
{
    int len = my_wctomb(utf8_str, wc); // 将宽字符转换为 UTF-8
    if (len == -1)
    {
        printf("Error converting wide character to UTF-8.\n");
        utf8_str[0] = '\0'; // 设置空字符串
    }
}

// 居中显示一个字符，直接通过光标移动来实现
void center_char(wchar_t wc, unsigned int width, unsigned int height)
{
    char utf8_str[4]; // 存储 UTF-8 字符串的缓冲区

    // 将 Unicode 字符转换为 UTF-8
    wcharToUtf8(wc, utf8_str);

    // 计算居中位置，假设终端尺寸为 width x height
    int col = (width - strlen(utf8_str)) / 2; // 水平居中
    int row = height / 2;                     // 垂直居中

    // 移动光标到居中位置
    MoveCursorTo(row, col);

    // 输出字符
    printf("%s", utf8_str);
}

void centerStr(const wchar_t *wcStr, unsigned int width, unsigned int height)
{
    if (wcStr && *wcStr)
    {
        // size_t strLen = wcslen(wcStr);

        size_t strLen = calculateActualWidth(wcStr);
        if (strLen > width)
        {
            return;
        }
        int col = (width - strLen) / 2;
        int row = height / 2;
        MoveCursorTo(row, col);

        char utf8Str[5];

        while (*wcStr != L'\0')
        {
            wcharToUtf8(*wcStr, utf8Str);
            printf("%s", utf8Str);
            wcStr++;
        }
    }
}

size_t calculateActualWidth(const wchar_t *wcStr)
{
    size_t width = 0;

    // 遍历宽字符字符串
    while (*wcStr != L'\0')
    {
        // 判断是否是中文字符（假设中文字符是大于 127 的）
        if (*wcStr > 127)
        {
            width += 2; // 中文字符宽度为 2
        }
        else
        {
            width += 1; // ANSI 字符宽度为 1
        }
        wcStr++; // 移动到下一个字符
    }

    return width;
}

void DrawC()
{
    static int rand = 0;
    rand++;
    int x = (80 - 16) / 2, y = 2;
    for (int i = 0; i < 8; i++)
    {
        for (int j = 0; j < 8; j++)
        {
            // SetFgColor(vt_fore_color(VT_F_WHITE + ( 4 + i) % 8));
            SetBgColor(vt_back_color(VT_B_BLACK + (rand + i + j) % 8));
            FillBox(x + 2 * i, y + j, 2, 1);
        }
    }
}
int main()
{
    system("chcp 65001");

    TesChar();
    StoreScreen();
    DisEnableCursor();
    // wchar_t wc = L'就';       // Unicode 字符，中文字符
    unsigned int width = 80;  // 假设终端宽度为 80 列
    unsigned int height = 24; // 假设终端高度为 24 行

    SetFgColor(VT_F_WHITE);
    SetBgColor(VT_B_BLUE);
    FillBox(0, 0, width, height);
    RenderBox(0, 0, width, height);

    // 居中显示字符
    // center_char(wc, width, height);

    centerStr(L"宽字符类型 wchar_t 是为了支持更大的字符集", width, height + 12);
    centerStr(L"按'q'退出播放", width, height + 14);

    while (1)
    {
        // 检查是否按下了键
        if (kbhit())
        {
            char ch = getch(); // 获取按下的键

            if (ch == 'q' || ch == 'Q')
            {
                printf("Exiting the program.\n");
                break; // 按下 'q' 或 'Q' 时退出循环
            }
        }

        // 执行需要定时调用的函数
        // DrawC();
        DrawNum();
        //DrawZh();

        // 延时 1 秒，避免程序过于频繁地执行
        Sleep(300); // 1000 毫秒 = 1 秒
    }

    MoveCursorTo(80, 24);
    system("pause");
    RestoreScreen();
    EnableCursor();

    return 0;
}
